Otázka č. 21 - Bloky, podmínky, cykly, kurzory a vyjímky
Bloky
- sekvence příkazů, která je uzavřena mezi klíčovými slovy BEGIN a END.
- Blok může obsahovat deklarace proměnných, výrazy, podmínky, cykly, a další bloky.
- Pomocí bloků lze vytvořit logické celky kódu, které mohou být samostatně spouštěny a znovu použity.
Části bloku
- Deklarace proměnných - Definice proměnných, které budou v bloku použity.
- Výkonná část - Obsahuje příkazy, které budou v bloku vykonány.
- Vyjímková část - Slouží k zachycení a ošetření výjimek, které mohou nastat během vykonávání bloku.
BEGIN
-- Deklarativní část
DECLARE proměnná INT;
-- Výkonná část
proměnná := 10;
SELECT * FROM tabulka WHERE sloupec = proměnná;
-- Výjimková část
EXCEPTION
WHEN nějaká_výjimka THEN
-- Ošetření výjimky
ROLLBACK;
END;
Nepojmenované bloky
- základní bloky, které nemají vlastní název a jsou často používány jako součást jiných bloků nebo vnořené v jiných konstrukcích.
BEGIN
DECLARE x INT DEFAULT 1;
SET x = x + 1;
SELECT x;
END;
Pojmenované bloky
- bloky, kterým je přiřazen název.
- V MariaDB jsou pojmenované bloky často procedury nebo funkce. Název bloku umožňuje jeho snadnější opakované použití a volání.
DELIMITER //
CREATE PROCEDURE moje_procedura()
BEGIN
DECLARE x INT DEFAULT 1;
SET x = x + 1;
SELECT x;
END //
DELIMITER ;
Vnořené bloky
- bloky, které jsou definovány uvnitř jiných bloků. To umožňuje rozdělit komplexní logiku do menších, lépe spravovatelných částí.
- Vnořené bloky mohou být nepojmenované i pojmenované.
BEGIN
DECLARE y INT DEFAULT 2;
BEGIN
DECLARE z INT;
SET z = y * 2;
SELECT z;
END;
SET y = y + 1;
SELECT y;
END;
Podmínky
- umožňují řídit tok programu na základě specifických podmínek.
- V MariaDB se podmínky nejčastěji používají v rámci procedur a funkcí k provádění různých akcí podle hodnot proměnných nebo výsledků dotazů. - MariaDB podporuje několik typů podmínek, včetně IF a CASE.
IF podmínka
- používá k provedení bloku kódu, pokud je určitá podmínka splněna.
- Může mít také volitelnou větev ELSEIF a ELSE pro zpracování alternativních podmínek.
IF podmínka THEN
-- Kód, který se vykoná, pokud je podmínka splněna
ELSEIF další_podmínka THEN
-- Kód, který se vykoná, pokud je splněna další_podmínka
ELSE
-- Kód, který se vykoná, pokud není splněna žádná z výše uvedených podmínek
END IF;
-------------------------------------------------------------
DELIMITER //
CREATE PROCEDURE check_value(IN num INT)
BEGIN
IF num > 0 THEN
SELECT 'Number is positive';
ELSEIF num < 0 THEN
SELECT 'Number is negative';
ELSE
SELECT 'Number is zero';
END IF;
END //
DELIMITER ;
CASE podmínka
- možňuje zpracovat více podmínek a je podobná switch-case konstrukcím v jiných programovacích jazycích.
- CASE má dvě formy: jednoduchou a vyhledávací.
Jednoduchá forma
- porovnává jednu hodnotu s několika možnými hodnotami.
CASE výraz
WHEN hodnota1 THEN
-- Kód, který se vykoná, pokud výraz = hodnota1
WHEN hodnota2 THEN
-- Kód, který se vykoná, pokud výraz = hodnota2
ELSE
-- Kód, který se vykoná, pokud výraz neodpovídá žádné z výše uvedených hodnot
END CASE;
-------------------------------------------------------------
DELIMITER //
CREATE PROCEDURE check_grade(IN grade CHAR(1))
BEGIN
CASE grade
WHEN 'A' THEN
SELECT 'Excellent';
WHEN 'B' THEN
SELECT 'Good';
WHEN 'C' THEN
SELECT 'Fair';
WHEN 'D' THEN
SELECT 'Poor';
ELSE
SELECT 'Fail';
END CASE;
END //
DELIMITER ;
Vyhledávací forma
- umožňuje posuzovat složitější podmínky pro každou větev.
CASE
WHEN podmínka1 THEN
-- Kód, který se vykoná, pokud je podmínka1 splněna
WHEN podmínka2 THEN
-- Kód, který se vykoná, pokud je podmínka2 splněna
ELSE
-- Kód, který se vykoná, pokud není splněna žádná z výše uvedených podmínek
END CASE;
-------------------------------------------------------------
DELIMITER //
CREATE PROCEDURE check_number(IN num INT)
BEGIN
CASE
WHEN num > 0 THEN
SELECT 'Number is positive';
WHEN num < 0 THEN
SELECT 'Number is negative';
ELSE
SELECT 'Number is zero';
END CASE;
END //
DELIMITER ;
Cykly
- umožňují opakované provádění sady příkazů, dokud není splněna určitá podmínka.
- MariaDB podporuje několik typů cyklů: LOOP, WHILE, REPEAT a FOR.
LOOP cyklus
- provádí blok příkazů nekonečně, dokud není explicitně ukončen pomocí příkazu LEAVE.
LOOP
-- Kód, který se opakuje
IF podmínka THEN
LEAVE;
END IF;
END LOOP;
-------------------------------------------------------------
DELIMITER //
CREATE PROCEDURE loop_example()
BEGIN
DECLARE x INT DEFAULT 0;
loop_label: LOOP
SET x = x + 1;
IF x >= 10 THEN
LEAVE loop_label;
END IF;
END LOOP;
END //
DELIMITER ;
- Výhoda
- Flexibilní struktura, která může být ukončena kdykoli.
- Nevýhoda
- Potenciál pro nekonečný cyklus, pokud není správně implementován podmíněný LEAVE.
WHILE cyklus
- provádí blok příkazů, dokud je podmínka pravdivá.
WHILE podmínka DO
-- Příkazy
END WHILE;
-------------------------------------------------------------
DELIMITER //
CREATE PROCEDURE while_example()
BEGIN
DECLARE x INT DEFAULT 0;
WHILE x < 10 DO
SET x = x + 1;
SELECT x;
END WHILE;
END //
DELIMITER ;
- Výhoda
- Jasná a jednoduchá syntaxe pro opakování, dokud je podmínka pravdivá.
- Nevýhoda
- Pokud podmínka nikdy nebude nepravdivá, může vést k nekonečnému cyklu.
REPEAT cyklus
- Provádí blok příkazů alespoň jednou a pak opakuje, dokud není podmínka splněna.
REPEAT
-- Příkazy
UNTIL podmínka
END REPEAT;
-------------------------------------------------------------
DELIMITER //
CREATE PROCEDURE repeat_example()
BEGIN
DECLARE x INT DEFAULT 0;
REPEAT
SET x = x + 1;
SELECT x;
UNTIL x >= 10
END REPEAT;
END //
DELIMITER ;
- Výhody
- Zaručuje, že se blok příkazů vykoná alespoň jednou.
- Nevýhody
- Stejně jako u WHILE, může vést k nekonečnému cyklu, pokud podmínka nikdy nebude splněna.
FOR cyklus
- Používá se k opakování určitého bloku kódu pevně stanovený početkrát.
FOR x IN podmínka kolikrát má běžet DO
-- Příkazy
END FOR;
-------------------------------------------------------------
DELIMITER //
CREATE PROCEDURE for_example()
BEGIN
DECLARE x INT;
FOR x IN 1..10 DO
SELECT x;
END FOR;
END //
DELIMITER ;
- Výhody
- Jednoduchá syntaxe pro opakování bloku kódu pevně stanovený početkrát.
- Nevýhody
- Není vhodný pro situace, kdy není známý pevný počet opakování.
Kurzory
-
používají k iteraci přes řádky výsledků dotazu a umožňují zpracovávat jednotlivé řádky jednu po druhé.
-
To je užitečné, když potřebujete provádět složité operace nebo manipulace nad každým řádkem výsledku.
-
Interní kurzory
- Spravovány automaticky SQL serverem a uživatel k nim nemá přímý přístup. Používají se v běžných SQL dotazech.
-
Externí kurzory
- Definovány uživatelem a umožňují iteraci přes řádky výsledku dotazu explicitně, s přímou kontrolou nad kurzorem.
Základní příkazy
1.DECLARE CURSOR
- Definuje kurzor a přiřazuje mu výsledek dotazu.
DECLARE cursor_name CURSOR FOR SELECT sloupec1, sloupec2 FROM tabulka WHERE podmínka;
2. OPEN
- Otevření kurzoru a inicializace výsledkové sady.
OPEN cursor_name;
3. FETCH
- Načtení dalšího řádku z výsledkové sady kurzoru do proměnných.
FETCH cursor_name INTO proměnná1, proměnná2;
4. CLOSE
- Uzavření kurzoru a uvolnění zdrojů.
CLOSE cursor_name;
Příklad
DELIMITER //
CREATE PROCEDURE cursor_example()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE v_sloupec1 INT;
DECLARE v_sloupec2 VARCHAR(100);
DECLARE my_cursor CURSOR FOR SELECT sloupec1, sloupec2 FROM tabulka;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN my_cursor;
my_loop: LOOP
FETCH my_cursor INTO v_sloupec1, v_sloupec2;
IF done THEN
LEAVE my_loop;
END IF;
-- Zpracování řádku
SELECT v_sloupec1, v_sloupec2;
END LOOP;
CLOSE my_cursor;
END //
DELIMITER ;
Kurzor s parametry
- mohou také používat parametry, což umožňuje větší flexibilitu při vytváření dynamických dotazů.
DELIMITER //
CREATE PROCEDURE cursor_with_param(IN input_param INT)
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE v_sloupec1 INT;
DECLARE v_sloupec2 VARCHAR(100);
DECLARE my_cursor CURSOR FOR SELECT sloupec1, sloupec2 FROM tabulka WHERE sloupec1 = input_param;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN my_cursor;
my_loop: LOOP
FETCH my_cursor INTO v_sloupec1, v_sloupec2;
IF done THEN
LEAVE my_loop;
END IF;
-- Zpracování řádku
SELECT v_sloupec1, v_sloupec2;
END LOOP;
CLOSE my_cursor;
END //
DELIMITER ;
Vyjímky
-
slouží k zachycení a ošetření chyb nebo neočekávaných událostí, které nastanou během provádění SQL příkazů v uložených procedurách, funkcích nebo blocích kódu.
-
Použití výjimek umožňuje lepší kontrolu nad chybami a umožňuje správně reagovat na různé situace, které mohou nastat během běhu programu.
-
V MariaDB se ošetřování výjimek provádí pomocí HANDLERU.
-
Zlepšení robustnosti a spolehlivosti aplikací.
-
Poskytování uživatelsky přívětivějších chybových zpráv.
-
Logování chyb a provádění nápravných opatření.
DECLARE handler_type HANDLER FOR condition_value_list statement;
- handler_type
- Může být CONTINUE (pokračovat) nebo EXIT (ukončit).
- condition_value_list
- Seznam chybových kódů nebo stavů, které mají být zachyceny.
- statement
- Příkazy, které se mají vykonat, pokud je zachycena výjimka.
Příklad
DELIMITER //
CREATE PROCEDURE example_procedure()
BEGIN
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
-- Ošetření výjimky
ROLLBACK;
SELECT 'Chyba nastala a byla ošetřena.';
END;
-- Hlavní kód
START TRANSACTION;
-- Nějaké operace
COMMIT;
END //
DELIMITER ;
Druhy výjimek
- SQLSTATE a místní chyby (local errors).
SQLSTATE
-
kódy jsou standardizované pětimístné chybové kódy používané v SQL pro označení konkrétních typů chyb. Jsou univerzální napříč různými databázovými systémy.
-
Příklady SQLSTATE kódů
- 23000 - Porušení omezení integrity
- 42000 - Chyba syntaxe
- 01000 - Varování
- 02000 - Žádné další řádky
DECLARE EXIT HANDLER FOR SQLSTATE '23000'
BEGIN
-- Ošetření porušení omezení integrity
ROLLBACK;
SELECT 'Porušení omezení integrity.';
END;
Místní chyby
-
jsou specifické pro daný DBMS a mohou být vyjádřeny číselnými kódy nebo specifickými výrazy.
-
Příklady místních chyb v MariaDB
- 1062 - Duplicitní klíč
- 1146 - Neexistující tabulka
DECLARE EXIT HANDLER FOR 1062
BEGIN
-- Ošetření duplicitního klíče
ROLLBACK;
SELECT 'Duplicitní klíč nalezen.';
END;